#include "CoCoA/library.H"
#include <cstdlib>
#include <ctime>
#include <string>
#include <set>
#include <sstream>
#include <algorithm>


using namespace CoCoA;
using namespace std;

string ConvertToString(const RingElem & r){
			ostringstream oStr;
			oStr << r;
			return oStr.str();
} 

symbol string2symbol(string str){
	return symbol(str);
}

pair<RingHom, RingHom> MergRings(const SparsePolyRing& R1, const SparsePolyRing& R2){
 	const vector<RingElem>& vars1 = indets(R1);
 	const vector<RingElem>& vars2 = indets(R2);
 	vector<string> Symbs(vars1.size());
	transform(vars1.begin(),vars1.end(),Symbs.begin(),ConvertToString);
	/*for (size_t i=0; i< vars1.size(); i++)
		Symbs.push_back(ConvertToString(vars1[i]));
	*/
	size_t n=Symbs.size();
 	vector<size_t> indices;
 	for (size_t i=0; i< vars2.size(); i++){
		string var=ConvertToString(vars2[i]);
		vector<string>::const_iterator fnd=find(Symbs.begin(),Symbs.end(),var);
		if (fnd == Symbs.end()){
			Symbs.push_back(ConvertToString(vars1[i]));
			//vector<RingElem>& images; // vector of elements in R2, of size #vars1
			indices.push_back(n++);
		}
		else {
			indices.push_back(fnd-Symbs.begin());
		}
	}

	vector<symbol> AllIndets(Symbs.size(),symbol("x"));
	transform(Symbs.begin(),Symbs.end(),AllIndets.begin(),string2symbol); // map by transform 
	SparsePolyRing R=NewPolyRing(CoeffRing(R1),AllIndets);// GetPolyRing
	vector<RingElem> NewVars=indets(R);
	vector<RingElem> img2;
	for(size_t i=0; i< vars2.size(); i++)
		img2.push_back(NewVars[indices[i]]);
 	return make_pair(PolyAlgebraHom(R1, R, vector(NewVars.begin(),NewVars.begin()+vars1.size())),PolyAlgebraHom(R2, R, img2));
}


RingElem myadd(const RingElem r1, const RingElem r2){
	SparsePolyRing R1=AsSparsePolyRing(owner(r1)), R2=AsSparsePolyRing(owner(r2));
	if (R1==R2) return r1+r2;
	else 
		pair<RingHom,RingHom> mmap=MergRings(R1,R2);
		return (mmap.first)(r1)+(mmap.second)(r2);
}

static const int MAXDEG=10;
static const int MAXCF=99;

void program()
{
  GlobalManager CoCoAFoundations;
  PolyRing R = NewPolyRing(RingQ(), symbols("x","y","z"));
  PolyRing R2 = NewPolyRing(RingQ(), symbols("x","y","z"));
  RingElem f=myadd(indet(R,0),indet(R2,1));
  GlobalOutput() << "The random generated polynomial is: " << f << endl;
}

int main()
{
  try
  {
    program();
    return 0;
  }
  catch (const CoCoA::ErrorInfo& err)
  {
    GlobalErrput() << "***ERROR***  UNCAUGHT CoCoA error";
    ANNOUNCE(err);
  }
  catch (const std::exception& exc)
  {
    GlobalErrput() << "***ERROR***  UNCAUGHT std::exception: " << exc.what() << endl;
  }
  catch(...)
  {
    GlobalErrput() << "***ERROR***  UNCAUGHT UNKNOWN EXCEPTION" << endl;
  }
  return 1;
}

//----------------------------------------------------------------------
// RCS header/log in the next few lines
// $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/examples/ex-factor1.C,v 1.1 2009/09/23 14:09:36 abbott Exp $
// $Log: ex-factor1.C,v $
// Revision 1.1  2009/09/23 14:09:36  abbott
// First example for (polynomial) factorization.
//
//

